home *** CD-ROM | disk | FTP | other *** search
/ Megarom / Megarom Macintosh CD Software (Quantum Leap)(1992).iso / APPS / Re-Animator ƒ / Re-animator.c < prev   
C/C++ Source or Header  |  1992-02-12  |  19KB  |  722 lines

  1. /*
  2.     Re-Animator 1.1.0:    Generic animation player.
  3.     
  4.     Written by:              Russell LaValle
  5.     Correspondence:        12-i Bimini Crossing
  6.                         Hampton, VA 23666
  7.  
  8.         Re-Animator is a relatively simple ( in retrospect ) PICS animation
  9.     player. It will read any file with PICTs resources and animate them
  10.     very quickly using CopyBits.
  11.     
  12.     
  13.     Enhancements since Re-Animator 1.0.1:
  14.         1.     The user now has the option to make the animation window appear
  15.             on the left edge of the screen- greatly improving speed.
  16.             
  17.         2.    As well as displaying each frame as it's loaded in, Re-Animator
  18.             shows a small window with a growing bar signifying its progress
  19.             loading the file.
  20.         
  21.         3.     The user can have the Open dialog box display all files or just
  22.             PICS files.
  23.     
  24.         4.    The speed of the animation can be selected from the menu bar.
  25.         
  26.         5.    Added a less boring Finder Icon, and the version resource to
  27.             the resource file.
  28.         
  29.         
  30.         One problem I found with other animation solutions using
  31.     only DrawPicture, was that they were extremely slow. Another problem
  32.     was when they animated certain PICTs, they didn't overwrite the 
  33.     underlying PICT on the screen with a new one- they just peformed an OR
  34.     operation. Clearing the last PICT manually, slowed the animation even
  35.     more. I couldn't find a share/freeware program to do this, so I wrote
  36.     my own.
  37.      
  38.         This is my first "real" Macintosh program. I'll continue
  39.     to improve it as I find/hear improvements needed.
  40.     
  41.         Re-Animator is Freeware. Do anything you'd like with it.
  42.         
  43.         I'd like to thank Dave Mark & CartWright Reed for the excellent
  44.     Macintosh Programming Primer Volume I. Also extremely helpful were
  45.     Brigham Stevens' offScreenBitMap.c routines. And of course, Think C is
  46.     an awesome/inexpensive developement environment.
  47.     
  48.         If you have a very large animation to run, you may need to enlarge
  49.     the application memory size in the Get Info box.
  50.         
  51.         Feel free to write me at the above address to comment or make
  52.     suggestions. I can also be reached on America Online: Russell FP
  53.     
  54.                     *************************************
  55.                     *  I did not include the Proj file  *
  56.                     *   because it was huge with the    *
  57.                     *  inclusion of the ANSI library.   *
  58.                     * When you create the project, just *
  59.                     * be sure to add:                    *
  60.                     *    1.    Re-Animator.c                *
  61.                     *    2.    MacTraps                    *
  62.                     *    3.    ANSI                        *
  63.                     *************************************    
  64. */
  65.  
  66. #include <stdlib.h>
  67.  
  68. #define NIL_POINTER            0L
  69. #define NIL_STRING            "\p"
  70. #define A_SECOND            60
  71.  
  72. #define NOTHING                NIL_STRING
  73. #define NO_FILTER            NIL_POINTER
  74. #define NO_HOOK                NIL_POINTER
  75. #define ALL_TYPES            -1
  76.  
  77. #define MIN_SLEEP            0L
  78. #define NIL_MOUSE_REGION    0L
  79. #define REMOVE_ALL_EVENTS    0
  80.  
  81. #define RECT_LEFT            10
  82. #define RECT_TOP            10
  83. #define RECT_RIGHT            212
  84. #define RECT_BOTTOM            25
  85.  
  86. #define PEN_HEIGHT            13
  87.  
  88. #define CANT_OPEN_FILE        400
  89. #define CANT_GET_RES        401
  90. #define OUT_OF_MEMORY        402
  91. #define NO_WINDOW_RES        403
  92. #define NO_PICTS            404
  93.  
  94. #define APPLE_MENU_ID        400
  95. #define FILE_MENU_ID        401
  96. #define SPEED_MENU_ID        403
  97. #define OPTION_MENU_ID        404
  98.  
  99. #define OUR_MBAR            400
  100. #define PROG_WINDOW            400
  101.  
  102. #define ABOUT_ITEM            1
  103.  
  104. #define OPEN_ITEM            1
  105. #define CLOSE_ITEM            2
  106. #define RUN_ITEM            4
  107. #define QUIT_ITEM            6
  108.  
  109. #define FAST_AS_POS            1
  110. #define ONE_SIXTIETH        2
  111. #define ONE_THIRTIETH        3
  112. #define ONE_TWENTIETH        4
  113. #define ONE_FIFTEENTH        5
  114. #define ONE_TENTH            6
  115. #define ONE_FIFTH            7
  116.  
  117. #define SUPER_FAST            1
  118. #define PICS_ONLY            3
  119.  
  120. #define ADD_CHECK            TRUE
  121. #define REMOVE_CHECK        FALSE
  122.  
  123. #define YES_GO_AWAY            TRUE
  124. #define MOVE_TO_FRONT        -1L
  125. #define LEAVE_THERE            FALSE
  126. #define VISIBLE                TRUE
  127.  
  128. #define ABOUT_ALERT            400
  129. #define ERROR_ALERT_ID        401
  130. #define MOTHER_ERROR        "\pCan't tell what error happened... Sorry."
  131.  
  132. Rect            destRect, sourceRect, picRect, frame1Rect, progressRect;
  133. int                numFrames, horizDiff, vertDiff, addFlag,
  134.                 animSpeed, lastSpeed, windRectTop, windRectLeft;
  135. Boolean            notDone = TRUE,
  136.                 fileLoaded, doneAnimating, errorDetected, superFastFlag,
  137.                 PICSOnlyFlag;
  138. BitMap            *theAnimation, lastBitMap;
  139. WindowRecord    animWindRec;
  140. WindowPtr        animateWindow, progressWindow;
  141. SFReply            theReply;
  142. MenuHandle        theAppleMenu, theFileMenu, theSpeedMenu, theOptionMenu;
  143. EventRecord        theEvent;
  144. PicHandle        thePict;
  145.  
  146. /********************************** main *****************/
  147. main()
  148. {
  149.     ToolBoxInit();                        /* call initialization routines    */
  150.     MenuBarInit(); 
  151.     InitProgWindow();
  152.     Alert( ABOUT_ALERT, NIL_POINTER );    /* display initial about box    */
  153.  
  154.     MainLoop(); 
  155. }
  156.  
  157. /********************************** ToolBoxInit **********/
  158. ToolBoxInit()
  159. {
  160.     InitGraf( &thePort );            /* standard initialization stuff    */
  161.     InitFonts();
  162.     FlushEvents( everyEvent, 0 );
  163.     InitWindows();
  164.     InitMenus();
  165.     TEInit();
  166.     InitDialogs( NIL_POINTER );
  167.     InitCursor();
  168. }
  169.  
  170. /********************************** MenuBarInit **********/
  171. MenuBarInit()
  172. {
  173.     Handle        theMenuBar;
  174.     
  175.     theMenuBar = GetNewMBar( OUR_MBAR );        /* load the menu bar     */
  176.     SetMenuBar( theMenuBar );                    /* make it active        */
  177.     theAppleMenu = GetMHandle( APPLE_MENU_ID );
  178.     AddResMenu( theAppleMenu, 'DRVR' );
  179.     theFileMenu = GetMHandle( FILE_MENU_ID );
  180.     theSpeedMenu = GetMHandle( SPEED_MENU_ID );
  181.     theOptionMenu = GetMHandle( OPTION_MENU_ID );
  182.     lastSpeed = 1;
  183.     CheckItem( theSpeedMenu, lastSpeed, ADD_CHECK );
  184.     PICSOnlyFlag = TRUE;
  185.     CheckItem( theOptionMenu, PICS_ONLY, PICSOnlyFlag );
  186.     superFastFlag = FALSE; 
  187.     DrawMenuBar();                                /* and display it        */
  188. }
  189.  
  190. /********************************** MainLoop *************/
  191. MainLoop()
  192. {
  193.     do
  194.     {
  195.         errorDetected = FALSE;       /* reset Error flag each time around    */
  196.         HandleEvent();
  197.     } while ( notDone );           /* keep going until we're done        */
  198.     CloseFile(theAnimation);
  199. }
  200.  
  201. /********************************** HandleEvent **********/
  202. HandleEvent()
  203. {
  204.     char        theKey;
  205.     
  206.     WaitNextEvent( everyEvent, &theEvent,        /* return an event        */
  207.         MIN_SLEEP, NIL_MOUSE_REGION );
  208.     
  209.     switch ( theEvent.what )
  210.     {
  211.         case mouseDown:                            /* check for mouse and    */
  212.             HandleMouseDown();                    /* keyboard events        */
  213.             break;
  214.         case keyDown:
  215.         case autoKey:
  216.             theKey = theEvent.message & charCodeMask;
  217.             if (( theEvent.modifiers & cmdKey ) != 0 )
  218.                     HandleMenuChoice( MenuKey( theKey ));
  219.             break;
  220.         case updateEvt:
  221.             if ( ( WindowPtr )theEvent.message == animateWindow )
  222.             {
  223.                 BeginUpdate( theEvent.message );
  224.                 DrawFrame( theAnimation );
  225.                 EndUpdate( theEvent.message );
  226.             }
  227.             break;
  228.     } /* switch */
  229. }
  230.  
  231. /********************************** HandleMouseDown ******/
  232. HandleMouseDown()
  233. {
  234.     WindowPtr    theWindow;
  235.     short int    thePart;
  236.     long int    menuChoice;
  237.     
  238.     thePart = FindWindow( theEvent.where, &theWindow );
  239.     switch ( thePart )
  240.     {
  241.         case inMenuBar:
  242.             menuChoice = MenuSelect( theEvent.where );
  243.             HandleMenuChoice( menuChoice );
  244.             break;
  245.         case inSysWindow:
  246.             SystemClick( &theEvent, theWindow );
  247.             break;
  248.     } /* case */
  249. }
  250.  
  251. /********************************** HandleMenuChoice *****/
  252. HandleMenuChoice( long int menuChoice )
  253. {
  254.     int             theMenu, theItem;
  255.     
  256.     if ( menuChoice != 0 )
  257.     {
  258.         theMenu = HiWord( menuChoice );        /* Get which item of which    */
  259.         theItem = LoWord( menuChoice );        /* menu was selected.        */
  260.         switch ( theMenu )
  261.         {
  262.             case APPLE_MENU_ID:
  263.                 HandleAppleChoice( theItem );
  264.                 break;
  265.             case FILE_MENU_ID:
  266.                 HandleFileChoice( theItem );
  267.                 break;
  268.             case SPEED_MENU_ID:
  269.                 HandleSpeedChoice( theItem );
  270.                 break;
  271.             case OPTION_MENU_ID:
  272.                 HandleOptionChoice( theItem );
  273.                 break;
  274.         } /* case */
  275.     } /* if */
  276.     HiliteMenu( 0 );
  277. }
  278.  
  279. /********************************** HandleAppleChoice ****/
  280. HandleAppleChoice( int theItem )
  281. {
  282.     Str255        accName;
  283.     int            accNumber;
  284.     short int    itemNumber;
  285.     
  286.     switch ( theItem )
  287.     {
  288.         case ABOUT_ITEM:
  289.             Alert( ABOUT_ALERT, NIL_POINTER );    /* generic alert to        */
  290.             break;                                /* show about info        */
  291.         default:
  292.             GetItem( theAppleMenu, theItem, accName );    /* Get and run    */
  293.             accNumber = OpenDeskAcc( accName );            /* a DA.        */
  294.             break;
  295.     } /* switch */
  296. }
  297.  
  298. /********************************** HandleFileChoice *****/
  299. HandleFileChoice( int theItem )
  300. {
  301.     switch ( theItem )
  302.     {
  303.         case OPEN_ITEM:
  304.             OpenFile();
  305.             break;
  306.         case CLOSE_ITEM:
  307.             CloseFile(theAnimation);
  308.             break;
  309.         case RUN_ITEM:
  310.             AnimateThem();
  311.             break;
  312.         case QUIT_ITEM:
  313.             notDone = FALSE;
  314.             break;
  315.     } /* switch */
  316. }
  317. /********************************** HandleSpeedChoice ****/
  318. HandleSpeedChoice( int theItem )
  319. {
  320.     switch ( theItem )
  321.     {
  322.         case FAST_AS_POS:
  323.             animSpeed = 0;
  324.             break;
  325.         case ONE_SIXTIETH:
  326.             animSpeed = 1;
  327.             break;
  328.         case ONE_THIRTIETH:
  329.             animSpeed = 2;
  330.             break;
  331.         case ONE_TWENTIETH:
  332.             animSpeed = 3;
  333.             break;
  334.         case ONE_FIFTEENTH:
  335.             animSpeed = 4;
  336.             break;
  337.         case ONE_TENTH:
  338.             animSpeed = 6;
  339.             break;
  340.         case ONE_FIFTH:
  341.             animSpeed = 12;
  342.             break;
  343.     } /* switch */
  344.     CheckItem( theSpeedMenu, lastSpeed, REMOVE_CHECK );
  345.     CheckItem( theSpeedMenu, theItem, ADD_CHECK );
  346.     lastSpeed = theItem;
  347. }
  348. /**********************************HandleOptionChoice ****/
  349. HandleOptionChoice( int theItem )
  350. {
  351.     switch ( theItem )
  352.     {
  353.         case SUPER_FAST:
  354.             superFastFlag = !superFastFlag;
  355.             if ( fileLoaded )
  356.                 if ( superFastFlag )
  357.                     MoveWindow( animateWindow, 0, windRectTop,
  358.                         LEAVE_THERE );
  359.                 else
  360.                     MoveWindow( animateWindow, windRectLeft, windRectTop,
  361.                         LEAVE_THERE );
  362.             CheckItem( theOptionMenu, SUPER_FAST, superFastFlag );
  363.             break;
  364.         case PICS_ONLY:
  365.             PICSOnlyFlag = !PICSOnlyFlag;
  366.             CheckItem( theOptionMenu, PICS_ONLY, PICSOnlyFlag );
  367.             break;
  368.     } /* switch */
  369. }
  370.  
  371. /********************************** OpenFile *************/
  372. OpenFile()
  373. {
  374.     GetPicsFile();
  375.     if (theReply.good)
  376.     {
  377.         LoadPics();
  378.         if ( !( errorDetected ) )                    /* If everything's    */
  379.         {                                            /* fine, enable and */
  380.             EnableItem( theFileMenu, CLOSE_ITEM );    /* disable certain    */
  381.             EnableItem( theFileMenu, RUN_ITEM );    /* menu items.        */
  382.             DisableItem( theFileMenu, OPEN_ITEM );
  383.         } /* if */
  384.     } /* if */
  385. }
  386.  
  387. /********************************** GetPicsFile **********/
  388. GetPicsFile()
  389. {
  390.     Point        dialogLoc;
  391.     SFTypeList    fileTypes;
  392.     int            numTypes;
  393.     
  394.     dialogLoc.h = 80;                /* set up location to place select    */
  395.     dialogLoc.v = 80;                /* dialog, then set type of file to */
  396.     fileTypes[ 0 ] = 'PICS';        /* show                             */
  397.     if ( PICSOnlyFlag )
  398.         numTypes = 1;
  399.     else
  400.         numTypes = ALL_TYPES;
  401.     SFGetFile( dialogLoc, NOTHING, NO_FILTER, numTypes,
  402.                 &fileTypes, NO_HOOK, &theReply);    /* Call file select */
  403. }                                                    /* dialog.            */
  404.  
  405. /********************************** CloseFile ************/
  406. CloseFile(BitMap *animation)
  407. {
  408.     OSErr        theResult;
  409.     int            i;
  410.  
  411.     if ( fileLoaded )
  412.     {
  413.         theResult = FSClose( theReply.vRefNum );    /* Close the file.    */
  414.         for ( i=0; i < numFrames; i++, animation++ )    
  415.         {
  416.             FreeBitMap( animation );                /* Release memory.    */
  417.         } /* for */
  418.         free( theAnimation );
  419.         free( &lastBitMap );
  420.         CloseWindow( animateWindow );
  421.         fileLoaded = FALSE;
  422.         DisableItem( theFileMenu, RUN_ITEM );        /* Enable/disable    */
  423.         DisableItem( theFileMenu, CLOSE_ITEM );        /* appropriate menu */
  424.         EnableItem( theFileMenu, OPEN_ITEM );        /* items.            */
  425.     } /* if */
  426. }
  427.  
  428. /********************************** LoadPics *************/
  429. LoadPics()
  430. {
  431.     short int    resRefNum;
  432.     int            i, incStep;
  433.     BitMap        *animation;
  434.     GrafPort    tempPort;
  435.         
  436.     if (( resRefNum = OpenRFPerm( theReply.fName,    /* Open the file.    */
  437.             theReply.vRefNum, fsRdPerm )) == -1 )
  438.     {
  439.         ErrorHandler( CANT_OPEN_FILE );
  440.     }
  441.     else
  442.     {
  443.         numFrames = Count1Resources( 'PICT' );        /* find # of PICTs    */
  444.         
  445.         if ( numFrames > 0 )
  446.         {
  447.             if ( 200 % numFrames )
  448.                 addFlag = 1;
  449.             else
  450.                 addFlag = 0;
  451.             theAnimation = ( BitMap * ) calloc( (unsigned)(numFrames),
  452.                                 sizeof(BitMap) );    /* allocate array    */
  453.             animation = theAnimation;            
  454.             GetMyPict( 0, animation );
  455.             GetAnimWindow( frame1Rect );
  456.             InitProgress();
  457.             OpenPort( &tempPort );
  458.             NewBitMap( &frame1Rect, &lastBitMap );
  459.             LoadPicture( animation++, 0, &tempPort );
  460.             fileLoaded = TRUE;                        /* set flag            */
  461.             if ( numFrames > 1 )
  462.             {
  463.                 for ( i=1; i < numFrames; i++, animation++ )
  464.                 {
  465.                     GetMyPict( i, animation );
  466.                     LoadPicture( animation, i, &tempPort );         /* fill fields    */
  467.                 } /* for */
  468.             } /* if */
  469.             ClosePort( &tempPort );
  470.             HideWindow( progressWindow );
  471.             DrawFrame( theAnimation );
  472.             SetPort( progressWindow );
  473.             PaintRect( &progressRect );
  474.         } /* if */
  475.         else
  476.         {
  477.             FSClose( theReply.vRefNum );    /* if no PICTs, close file    */
  478.             ErrorHandler( NO_PICTS );        /* display error message    */
  479.         } /* else */
  480.     } /* else */
  481. }
  482.  
  483. /********************************** GetMyPict ***********/
  484. GetMyPict( int frameNum, BitMap *theMap )
  485. {
  486.     
  487.     thePict = (PicHandle)Get1IndResource( 'PICT', frameNum + 1 );
  488.     
  489.     if ( ResError() == resNotFound )
  490.     {
  491.         ErrorHandler( CANT_GET_RES );
  492.     } /* if */
  493.     else
  494.     {
  495.         picRect = ( **thePict ).picFrame;
  496.         RemoveSpace( &picRect, frameNum );
  497.         if ( frameNum == 0 )
  498.         {
  499.             frame1Rect = picRect;
  500.         }
  501.         NewBitMap( &frame1Rect, theMap );        /* allocate memory        */
  502.         
  503.         if ( MemErr )
  504.         {
  505.             DisposHandle( thePict );            /* if not enough memory    */
  506.             ErrorHandler( OUT_OF_MEMORY );        /* display message and    */
  507.         } /* if */
  508.     } /* else */
  509. }
  510.  
  511. /********************************** LoadPicture **********/
  512. LoadPicture( BitMap *theMap, int iteration, GrafPort *tPort )
  513. {    
  514.     int            hDraw;
  515.     
  516.     SetPort( tPort );
  517.     CopyBits( &lastBitMap, theMap, &frame1Rect, &frame1Rect,
  518.                 srcCopy, NIL_POINTER );
  519.     SetPortBits( theMap );                            /* draw the PICT in    */
  520.     FillRect( &picRect, white );                    /* each BitMap that */
  521.     DrawPicture( thePict, &picRect );                /* we allocated        */
  522.     DisposHandle( thePict );
  523.     CopyBits( theMap, &lastBitMap, &frame1Rect, &frame1Rect,
  524.                 srcCopy, NIL_POINTER );
  525.     SetPort( animateWindow );
  526.     DrawFrame( theMap );
  527.     SetPort( progressWindow );
  528.     hDraw = 200 * ( iteration + 1 ) / numFrames + RECT_LEFT + addFlag;
  529.     LineTo ( hDraw, RECT_TOP + 1 );
  530. }
  531.  
  532. /********************************** InitProgWindow *******/
  533. InitProgWindow()
  534. {
  535.     progressWindow = GetNewWindow( PROG_WINDOW, NIL_POINTER,
  536.                         MOVE_TO_FRONT );
  537.     PenMode( patCopy );
  538.     animSpeed = 0;
  539. }
  540.  
  541. /********************************** InitProgress *********/
  542. InitProgress()
  543. {
  544.     SelectWindow( progressWindow );
  545.     SetPort( progressWindow );
  546.     SetRect ( &progressRect, RECT_LEFT, RECT_TOP,
  547.                     RECT_RIGHT, RECT_BOTTOM );
  548.     ShowWindow( progressWindow );
  549.     FillRect( &progressRect, white );
  550.     PenSize( 1, 1 );
  551.     PenPat( black );
  552.     FrameRect ( &progressRect );
  553.     MoveTo( 60, 40 );
  554.     DrawString( "\pLoading PICTs...");
  555.     MoveTo( RECT_LEFT + 1, RECT_TOP + 1 );
  556.     PenSize( 1, PEN_HEIGHT );
  557.     PenPat( gray );
  558. }        
  559.  
  560. /********************************** FreeBitMap ***********/
  561. FreeBitMap( BitMap *Bits )
  562. {
  563.     DisposPtr( Bits->baseAddr );            /* free up a BitMap Ptr        */
  564.     Bits->baseAddr = NIL_POINTER;            /* and it's memory            */
  565.     SetRect( &Bits->bounds, 0,0,0,0 );
  566.     Bits->rowBytes = 0;
  567. }
  568.  
  569. /********************************** NewBitMap ************/
  570. NewBitMap( Rect *frame, BitMap *theMap )
  571. {
  572.     int            size, rbytes;
  573.     
  574.     CalcOffScreen( frame, &size, &rbytes );        /* find amount of mem.    */
  575.     theMap->rowBytes = rbytes;                    /* to allocate, and set    */
  576.     theMap->bounds = *frame;                    /* up a Ptr to do that    */
  577.     theMap->baseAddr = NewPtr( size );
  578. }
  579.  
  580. /********************************** CalcOffScreen ********/
  581. CalcOffScreen( frame, needed, rows )
  582. register Rect    *frame;
  583. register int    *needed;
  584. register int    *rows;
  585. {
  586.     *rows = (((( frame->right) - ( frame->left )) + 15)/16 ) * 2;
  587.     *needed = (( *rows ) * (( frame->bottom ) - ( frame->top )));
  588. }
  589.  
  590. /********************************** GetAnimWindow ************/
  591. GetAnimWindow( Rect theRect )
  592. {
  593.     Rect        windRect;
  594.     
  595.     sourceRect = theRect;
  596.     destRect = theRect;
  597.     
  598.     GetContent( &windRect );
  599.     ClipPicOrWindow( &windRect );
  600.     windRectTop = windRect.top;
  601.     windRectLeft = windRect.left;
  602.     if ( superFastFlag )
  603.         OffsetRect( &windRect, -( windRect.left ), 0 );
  604.     animateWindow = NewWindow( &animWindRec, &windRect, "\pRe-Animator",
  605.                         VISIBLE, plainDBox, MOVE_TO_FRONT,
  606.                         YES_GO_AWAY, 8 );
  607. }
  608. /********************************** GetContent ***********/
  609. GetContent(Rect *windRect)
  610. {
  611.     *windRect = screenBits.bounds;             /* determine a baseline        */
  612.     windRect->top += ( MBarHeight + 2 );    /* window size by coming in    */
  613.     windRect->bottom -= 2;                    /* from  top ( top + MBAR ) */
  614.                                             /* and bottom.                 */
  615. }
  616.  
  617. /********************************** ClipPicOrWindow ******/
  618. ClipPicOrWindow( Rect *windRect)
  619. {
  620.     int            windWidth, windHeight,
  621.                 rectWidth, rectHeight;
  622.     windWidth = windRect->right - windRect->left;
  623.     windHeight = windRect->bottom - windRect->top;
  624.     rectWidth = sourceRect.right;
  625.     rectHeight = sourceRect.bottom;
  626.     
  627.     if ( rectWidth > windWidth )
  628.     {
  629.         sourceRect.left = ( rectWidth - windWidth )/2;    /* clip center    */
  630.         sourceRect.right = sourceRect.left + windWidth;    /* of picture    */
  631.         destRect.right = windWidth;                        /* horizontally    */
  632.     } /* if */
  633.     else
  634.     {
  635.         windRect->left += ( windWidth - rectWidth )/2;    /* size window    */
  636.         windRect->right = windRect->left + rectWidth;    /* horizontally    */
  637.     } /* else */
  638.     
  639.     if ( rectHeight > windHeight )
  640.     {
  641.         sourceRect.top = ( rectHeight - windHeight )/2;    /* clip center    */
  642.         sourceRect.bottom = sourceRect.top + windHeight; /* of picture    */
  643.         destRect.bottom = windHeight;                    /* vertically    */
  644.     } /* if */
  645.     else
  646.     {
  647.         windRect->top += ( windHeight - rectHeight )/2;    /* size window    */
  648.         windRect->bottom = windRect->top + rectHeight;    /* vertically    */
  649.     } /* else */
  650. }
  651.  
  652. /********************************** RemoveSpace **********/
  653. RemoveSpace( Rect *theRect, int frameNum )
  654. {
  655.     if ( frameNum == 0 )
  656.     {
  657.         horizDiff = theRect->left;
  658.         vertDiff = theRect->top;
  659.     }
  660.     OffsetRect( theRect, -horizDiff, -vertDiff );
  661. }
  662.  
  663. /********************************** AnimateThem **********/
  664. AnimateThem()
  665. {
  666.     int            i;
  667.     long int    endTicks;
  668.     BitMap        *animation;
  669.     
  670.     if ( fileLoaded )
  671.     {
  672.         doneAnimating = FALSE;
  673.         SetPort( progressWindow );
  674.         HideCursor();
  675.         do
  676.         {
  677.             for ( i=0, animation = theAnimation; i < numFrames;
  678.                          i++, animation++)             /* run through PICS    */
  679.                 {
  680.                     endTicks = TickCount() + animSpeed;
  681.                     DrawFrame( animation );
  682.                     if ( animSpeed > FAST_AS_POS )
  683.                         while ( TickCount() < endTicks );
  684.                     if ( Button() )
  685.                     {
  686.                         doneAnimating = TRUE;
  687.                         break;
  688.                     } /* if */
  689.                 } /* for */
  690.         } while ( !( doneAnimating ));        /* til mouse button pressed */
  691.         ShowCursor();
  692.     } /* if */
  693. }
  694. /********************************** DrawFrame ************/
  695. DrawFrame( BitMap *theMap )
  696. {
  697.     CopyBits(     theMap,                                    /* from BitMap     */
  698.                 &( animWindRec.port.portBits ),            /* to BitMap    */
  699.                 &sourceRect,                            /* from Rect    */
  700.                 &destRect,                                /* to Rect        */
  701.                 srcCopy,                                /* xfer mode    */
  702.                 NIL_POINTER );                            /* mask region    */
  703. }
  704.  
  705. /********************************** ErrorHandler *********/
  706. ErrorHandler( int stringNum )
  707. {
  708.     StringHandle    errorStringH;
  709.     
  710.     if (( errorStringH = GetString( stringNum )) == NIL_POINTER )
  711.         ParamText( MOTHER_ERROR, NIL_STRING, NIL_STRING,
  712.                     NIL_STRING );    /* If we can't find error message,  */
  713.     else                            /* show panic message.                */
  714.     {
  715.         HLock( errorStringH );        /* find error message to display    */
  716.         ParamText( *errorStringH, NIL_STRING, NIL_STRING, NIL_STRING );
  717.         HUnlock( errorStringH );
  718.     }
  719.     StopAlert( ERROR_ALERT_ID, NIL_POINTER );    /* show alert, and         */
  720.     errorDetected = TRUE;                        /* set flag                */
  721.     ExitToShell();
  722. }